package com.ryan.spring.cloud.gateway.service;

import com.ryan.spring.cloud.gateway.model.GatewayDefine;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;

import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * Created by kaimin on 21/1/2019.
 * time : 18:19
 */
@Service
public class GateWayDefineServiceImpl implements GateWayDefineService{

    @Autowired
    private RouteDefinitionWriter routeDefinitionWriter;

    private ApplicationEventPublisher publisher;

    private static List<GatewayDefine> gatewayDefines=new ArrayList<>();
    static {
        GatewayDefine gatewayDefine=new GatewayDefine("user1","lb://user-center","[{\"args\": {\"_genkey_0\": \"/user/**\"}, \"name\": \"Path\"}]","[]");
        GatewayDefine gatewayDefine1=new GatewayDefine("user","lb://user-center","[{\"args\": {\"_genkey_0\": \"/user/**\"}, \"name\": \"Path\"}]","[]");
        GatewayDefine gatewayDefine2=new GatewayDefine("common","lb://common","[{\"args\": {\"_genkey_0\": \"/common/**\"}, \"name\": \"Path\"}]","[{\"args\": {}, \"name\": \"ValidateCodeGatewayFilter\"}]");
        gatewayDefines.add(gatewayDefine);
        gatewayDefines.add(gatewayDefine1);
        gatewayDefines.add(gatewayDefine2);
    }


    @Override
    public List<GatewayDefine> findAll() {
        return gatewayDefines;
    }

    /**
     * 获取动态定义的路由
     * @return
     * @throws Exception
     */
    @Override
    public String loadRouteDefinition() throws Exception {
        try {
            List<GatewayDefine> gatewayDefineServiceAll = this.findAll();
            if (gatewayDefineServiceAll == null) {
                return "none route defined";
            }
            for (GatewayDefine gatewayDefine : gatewayDefineServiceAll) {
                RouteDefinition definition = new RouteDefinition();
                definition.setId(gatewayDefine.getId());
                definition.setUri(new URI(gatewayDefine.getUri()));
                List<PredicateDefinition> predicateDefinitions = gatewayDefine.getPredicateDefinition();
                if (predicateDefinitions != null) {
                    definition.setPredicates(predicateDefinitions);
                }
                List<FilterDefinition> filterDefinitions = gatewayDefine.getFilterDefinition();
                if (filterDefinitions != null) {
                    definition.setFilters(filterDefinitions);
                }
                routeDefinitionWriter.save(Mono.just(definition)).subscribe();
                this.publisher.publishEvent(new RefreshRoutesEvent(this));
            }
            return "success";
        } catch (Exception e) {
            e.printStackTrace();
            return "failure";
        }

    }

    @Override
    public GatewayDefine save(GatewayDefine gatewayDefine) throws Exception {
        gatewayDefines.add(gatewayDefine);
        return gatewayDefine;
    }

    @Override
    public void deleteById(String id) throws Exception {
        int index=-1;
        for (int i=0;i<gatewayDefines.size();i++) {
            if (gatewayDefines.get(i).getId().equals(id)) {
                index=i;
            }
        }

        if (index>=0)
        gatewayDefines.remove(index);

    }

    @Override
    public boolean existsById(String id) throws Exception {
        final boolean[] result = {false};
        gatewayDefines.stream().forEach((GatewayDefine gatewayDefine) -> {
            if (gatewayDefine.getId().equals(id)) {
                result[0] =true;
            }
        });
        return result[0];
    }
}
